#include <stdio.h>
#include <unistd.h>

#define oops(m,x) {perror(m); exit(x);}

main(){
    int pid, todc[2], fromdc[2];
    
    if( pipe(todc) == -1 || pipe(fromdc) == -1 ){
        oops("pipe failed\n", 1);
    }
    if( (pid = fork()) == -1){
        oops("cannot fork\n", 2);
    }

    // Child process ;
    if( pid == 0){
        be_dc(todc, fromdc);
    }
    // Parent process ;
    else{
        be_bc(todc, fromdc);
        wait(NULL);
    }
}

be_dc(int in[2], int out[2]){
    // 
    if( dup2(in[0], 0) == -1){
        oops("dc: cannot redirect stdin\n", 3);
    }
    close(in[0]);   // move to fd 0. 0 is redirected.
    close(in[1]);   // won't write here.

    if( dup2(out[1], 1) == -1){
        oops("dc: cannot redirect stdout\n", 4);
    }
    close(out[1]);  // move to fd 1. 1 is redirected.
    close(out[0]);  // won't read here.

    execlp("dc", "dc", "-", NULL);
    oops("Cannot run dc\n", 5);
}

be_bc(int todc[2], int fromdc[2]){
    int num1, num2 ;
    char operation[BUFSIZ], message[BUFSIZ], *fgets();
    FILE * fpout, * fpin, * fdopen() ;

    close(todc[0]);
    close(fromdc[1]);

    fpout = fdopen(todc[1], "w");
    fpin = fdopen(fromdc[0], "r");

    if(fpin == NULL || fpout == NULL )
    {
        fatal("Error converting pipes to streams");
    }

    // main loop 
    while( printf("tinybc:"), fgets(message, BUFSIZ, stdin) != NULL){
        // parse input :
        if( sscanf( message, "%d%[-+*/^]%d", &num1, operation, &num2) != 3){
            printf("Input syntax error\n");
            continue ;
        }

        if( fprintf( fpout, "%d\n%d\n%c\np\n", num1, num2, *operation) == EOF){
            fatal("Error writing to pipe towards dc\n");
        }
        fflush(fpout); // write to file(the pipe towards dc)
        if( fgets(message, BUFSIZ, fpin) == NULL){
            break;
        }
        printf("%d %c %d = %s", num1, *operation, num2, message);
    }

    fclose(fpout);
    fclose(fpin);
}

void fatal( char * mess[]){
    fprintf( stderr, "Error:%s\n", mess);
    exit(1);
}